﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Linq;
using DataContexts.Supplier;
using System.Collections.Generic;

/// <summary>
/// Summary description for SearchQuery
/// </summary>
public class SearchQuery
{
    private SupplierDataContext supplierContext = new SupplierDataContext();

    public int CountryId { get; set; }
    public int RegionId { get; set; }
    public int LocationId { get; set; }
    public DateTime PickUpDate { get; set; }
    public DateTime DropDate { get; set; }
    public decimal PickUpTime { get; set; }
    public decimal DropTime { get; set; }

    public Enums.Transmissions Transmission { get; set; }
    public Enums.ACOptions ACOption { get; set; }

    public int AdultCapacity { get; set; }
    public int ChildrenCapacity { get; set; }
    public int LuggageCapacity { get; set; }

    public int CurrentPageIndex { get; set; }
    public int PageSize { get; set; }

    public int SupplierVehicleId { get; set; }
    public int SupplierLocationId { get; set; }
    public int SupplierLocationVehicleId { get; set; }
    public int SupplierId { get; set; }

    public SearchQuery() { }

    public SearchResults Execute()
    {
        SearchResults result = new SearchResults();

        if (CurrentPageIndex == 0)
            CurrentPageIndex = 1;
        if (PageSize == 0)
            PageSize = Constants.DEFAULT_PAGESIZE;

        int skip = 0;
        if (CurrentPageIndex > 1)
            skip = PageSize * (CurrentPageIndex - 1);

        IList<ResultRow> fullResults = PopulateQuery();

        result.TotalRecords = fullResults.Count;

        result.Rows = (from r in fullResults
                       orderby r.Total ascending
                       select r).Skip(skip).Take(PageSize).ToList();

        return result;
    }

    private IList<ResultRow> PopulateQuery()
    {
        string[] time = PickUpTime.ToString(Constants.DECIMAL_FORMAT).Split('.');
        DateTime tripStart = PickUpDate.AddHours(Convert.ToDouble(time[0])).AddMinutes(Convert.ToDouble(time[1]));
        time = DropTime.ToString(Constants.DECIMAL_FORMAT).Split('.');
        DateTime tripEnd = DropDate.AddHours(Convert.ToDouble(time[0])).AddMinutes(Convert.ToDouble(time[1]));

        IList<ResultRow> fullResults = (from SP in supplierContext.Suppliers
                                        join SPL in supplierContext.SupplierLocations on SP.SupplierId equals SPL.SupplierId
                                        join ST_SPLT in supplierContext.SupplierLocationTimes on SPL.SupplierLocationId equals ST_SPLT.SupplierLocationId
                                        join END_SPLT in supplierContext.SupplierLocationTimes on SPL.SupplierLocationId equals END_SPLT.SupplierLocationId
                                        join SPV in supplierContext.SupplierVehicles on SP.SupplierId equals SPV.SupplierId
                                        join SPLV in supplierContext.SupplierLocationVehicles on SPL.SupplierLocationId equals SPLV.SupplierLocationId
                                        join PS in supplierContext.PriceOnSeasons on SPLV.SupplierLocationVehicleId equals PS.SupplierLocationVehicleId

                                        join PD in supplierContext.PriceOnDays on PS.PriceOnSeasonId equals PD.PriceOnSeasonId into PDs
                                        from PD in PDs.Where(pd => pd.SupplierLocationVehicleId == SPLV.SupplierLocationVehicleId && pd.StartDays <= supplierContext.GetTripDays(tripStart, tripEnd, SP.GracePeriodMins) && pd.EndDays >= supplierContext.GetTripDays(tripStart, tripEnd, SP.GracePeriodMins)).DefaultIfEmpty()

                                        where SPLV.SupplierVehicleId == SPV.SupplierVehicleId &&
                                              PS.StartDate <= tripStart && PS.EndDate >= tripEnd &&
                                              ST_SPLT.Day == Convert.ToInt16(tripStart.DayOfWeek) + 1 && ST_SPLT.StartTime.Value <= PickUpTime && ST_SPLT.EndTime >= PickUpTime &&
                                              END_SPLT.Day == Convert.ToInt16(tripEnd.DayOfWeek) + 1 && END_SPLT.StartTime.Value <= DropTime && END_SPLT.EndTime >= DropTime &&
                                              (Transmission == Enums.Transmissions.None || (SPV.AutoTransmission == (Transmission == Enums.Transmissions.Automatic ? true : false))) &&
                                              (ACOption == Enums.ACOptions.None || (SPV.AirCondition == (ACOption == Enums.ACOptions.AC ? true : false))) &&
                                              (AdultCapacity == 0 || (SPV.AdultCapacity >= AdultCapacity)) &&
                                              (ChildrenCapacity == 0 || (SPV.ChildrenCapacity >= ChildrenCapacity)) &&
                                              (LuggageCapacity == 0 || (SPV.LaggageCapacity >= LuggageCapacity)) &&
                                              (SPV.SupplierVehicleId == SupplierVehicleId || SupplierVehicleId == 0) &&
                                              (SPL.SupplierLocationId == SupplierLocationId || SupplierLocationId == 0) &&
                                              (SPLV.SupplierLocationVehicleId == SupplierLocationVehicleId || SupplierLocationVehicleId == 0) &&
                                              (SPLV.LocationId == LocationId) &&
                                              (SP.SupplierId == SupplierId || SupplierId == 0)
                                        select
                                        new ResultRow
                                        {
                                            Total = (PD == null ? PS.RentSellPrice : PD.RentSellPrice) * supplierContext.GetTripDays(tripStart, tripEnd, SP.GracePeriodMins),
                                            TripDays = supplierContext.GetTripDays(tripStart, tripEnd, SP.GracePeriodMins),
                                            SellPrice = (PD == null ? PS.RentSellPrice : PD.RentSellPrice),
                                            Price = (PD == null ? PS.RentPrice : PD.RentPrice),
                                            PriceOnDay = PD,
                                            PriceOnSeason = PS,
                                            Supplier = SP,
                                            SupplierId = SP.SupplierId,
                                            SupplierLocationId = SPL.SupplierLocationId,
                                            SupplierLocationVehicleId = SPLV.SupplierLocationVehicleId,
                                            SupplierVehicleId = SPV.SupplierVehicleId,
                                            Vehicle = SPV
                                        }).ToList();
        return fullResults;
    }

}
